今日內容:多型(Polymorphism)、getter & setter methods、aggregation、contribution、wrapper classes、ArrayLists
繼承相同parent class的多個subclass,在程式內可以先宣告一個parent class出來,接著在執行時期(runtime)依據使用者的輸入或選擇後才決定進行哪個subclass物件的建構
public class Animal{
void speak(){
System.out.println("The animal speaks");
}
}
public class Dog extends Animal{
@Override
void speak(){
System.out.println("The dog says woof");
}
}
public class Cat extends Animal{
@Override
void speak(){
System.out.println("The cat says meow");
}
}
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Animal animal; // 先宣告出parent class
Scanner scanner = new Scanner(System.in);
System.out.print("You would like a dog or a cat? (1 = dog, 2 = cat): ");
int choice = scanner.nextInt();
if(choice == 1){
animal = new Dog();
animal.speak(); // The dog says woof
}
else if(choice == 2){
animal = new Cat();
animal.speak(); // The cat says meow
}
else{
System.out.println("Invalid input");
}
scanner.close();
}
}
在class中為了保障資料安全,宣告資料型態的前面加上 private 關鍵字就可以讓他在main中不被直接存取(hide)
這時候就需要另外寫 get 和 set funtions(getter and setter)來修改這些private的數值
另外,加上final會使其變得無法被修改,可用於你不想讓其被修改的資料
public class Bank{
private double balance;
void deposit(double balance){
if(balance > 0.0){
this.balance += balance;
}
}
void withdraw(double balance){
if(balance > this.balance){
this.balance -= balance;
}
}
}
一個物件中 "has-a" 其他物件,例如Library中會有Book,就算Library不在了,Book也可以被轉移到其他地方,意味著兩者可以同時各自獨立存在
public class Book {
String title;
String author;
Book(String title, String author) {
this.title = title;
this.author = author;
}
void displayInfo() {
System.out.println("Book: \"" + title + "\" by " + author);
}
}
public class Library {
String name;
Book[] books;
int bookCount;
Library(String name, int capacity) {
this.name = name;
this.books = new Book[capacity];
this.bookCount = 0;
}
void addBook(Book book) {
if (bookCount < books.length) {
this.books[bookCount] = book;
bookCount++;
} else {
System.out.println("Library is full");
}
}
void listBooks() {
System.out.println("--- " + name + " ---");
for (int i = 0; i < bookCount; i++) {
books[i].displayInfo();
}
}
}
public class Main {
public static void main(String[] args) {
// Book可以被獨立宣告
Book book1 = new Book("Effective Java", "Joshua Bloch");
Book book2 = new Book("Clean Code", "Robert C. Martin");
Library cityLibrary = new Library("LA Library", 5);
// 宣告完Library後將Book加入
cityLibrary.addBook(book1);
cityLibrary.addBook(book2);
cityLibrary.listBooks();
}
}
一個物件是 "part of" 其他物件,等於A存在於B之中,當B物件不再存在時就再也不可存取到A物件
可以將大型物件切割成很多更小的物件
public class Engine{
String type;
Engine(String type){
this.type = type;
}
}
public class Car{
String model;
int year;
Engine engine;
Car(String model, int year, String engineType){
this.model = model;
this.year = year;
this.engine = new Engine(engineType);
}
}
用來將基礎資料型態(primitive)轉換成class的形式,可以用在物件中
// Autoboxing
Integer a = new Integer(123); // equal to Integer a = 123;
Double b = new Double(3.14); // = 3.14;
Character c = new Character('$'); // = '$';
Boolean d = new Boolean(true); // = true;
String e = "Pizza"; // 我們平常宣告String就是在用這個方式
// Unboxing
int x = a;
double y = b;
char z = c;
// ...
但是為什麼要把它換成wrapper class的形式?
其一是因為可以使用toString函式:
String a = Integer.toString(123);
String b = Double.toString(3.14);
String c = Character.toString('@');
String d = Boolean.toString(false);
String x = a + b + c + d; // 1233.14@false
另外也可以將String轉回去對應的資料型態:
int a = Integer.parseInt("123");
double b = Double.parseDouble("3.14");
char c = "Pizza".charAt(0); // char沒有parse method,要使用charAt
boolean d = Boolean.parseBoolean("true");
而在Character之下,也有一些utility methods可以用
Character.isLetter(參數); // 檢查是否為a-Z,回傳bool
Character.isUpperCase(參數); // 檢查是否為大寫,回傳bool
不過最主要的原因還是因為要將他轉換成class的形式,在下面ArrayList會提到
可以用來存物件(包括wrapper class),可以變動大小(動態陣列),用下來的感覺很像C++中的vector
import java.util.ArrayList;
public class Main{
public static void main(String[] args){
ArrayList<Integer> list = new ArrayList<>(); // 前面需要提供型態,後面不用
// 也可以宣告成其他wrapper class: Double, Boolean, String 或者是自己的class
list.add(3); // 很像vector的push_back()
list.add(1);
list.add(2);
System.out.println(list); // [3, 1, 2] <- 顯示在terminal的樣子
list.remove(0); // 括號內填index
System.out.println(list); // [1, 2]
list.set(0, 4); // vector的replace(),括號填入(index, 值)
System.out.println(list.get(0)); // 4 用get(index)進行特定位置的資料存取
System.out.println(list.size()); // 2 用size()取得List大小
}
}
如果要sort這個ArrayList,需要import另一個函式庫(Collections)
import java.util.Collections;
Collections.sort(list);
今天是接觸Java OOP的第三天,感覺起來越學頭越大,開始出現比較多細微的差距需要理解,並且有想到很多的問題,不過總而言之今天也是快樂學習的一天,明天繼續!